package com.zgx.plus.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.SqlHelper;
import com.zgx.plus.common.aop.DataScope;
import com.zgx.plus.common.constant.ComConstant;
import com.zgx.plus.common.exception.BizException;
import com.zgx.plus.common.utils.SecurityUtils;
import com.zgx.plus.system.api.dto.SysUserDto;
import com.zgx.plus.system.api.pos.SysUser;
import com.zgx.plus.system.api.pos.SysUserPost;
import com.zgx.plus.system.api.pos.SysUserRole;
import com.zgx.plus.system.api.vos.SysPostVo;
import com.zgx.plus.system.api.vos.SysRoleVo;
import com.zgx.plus.system.api.vos.SysUserVo;
import com.zgx.plus.system.mapper.SysUserMapper;
import com.zgx.plus.system.service.*;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    @Resource
    private SysUserRoleService sysUserRoleService;
    @Resource
    private SysRoleService sysRoleService;
    @Resource
    private SysUserPostService sysUserPostService;
    @Resource
    private SysPostService sysPostService;
    @Resource
    private SysDeptService sysDeptService;

    /**
     * 根据条件分页查询用户列表
     *
     * @param user 用户信息
     * @return 用户信息集合信息
     */
    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<SysUser> selectUserList(SysUserDto user) {
        return this.baseMapper.selectUserList(user);
    }


    /**
     * 新增保存用户信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    @Transactional
    public boolean insertUser(SysUserVo user) {

        Assert.isFalse(SqlHelper.retBool(this.count(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getUserId, user.getUserId())
                        .eq(SysUser::getUserName, user.getUserName()).eq(SysUser::getDelFlag, ComConstant.FLAG_EXIST))),
                () -> new BizException(MessageFormat.format("新增用户{0}失败，登录账号已存在", user.getUserName())));

        Assert.isFalse(StrUtil.isNotBlank(user.getPhonenumber()) && SqlHelper.retBool(this.count(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getUserId, user.getUserId())
                        .eq(SysUser::getPhonenumber, user.getPhonenumber()).eq(SysUser::getDelFlag, ComConstant.FLAG_EXIST))),
                () -> new BizException(MessageFormat.format("新增用户{0}失败，手机号码{1}已存在", user.getUserName(), user.getPhonenumber())));

        Assert.isFalse(StrUtil.isNotBlank(user.getEmail()) && SqlHelper.retBool(this.count(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getUserId, user.getUserId())
                        .eq(SysUser::getEmail, user.getEmail()).eq(SysUser::getDelFlag, ComConstant.FLAG_EXIST))),
                () -> new BizException(MessageFormat.format("新增用户{0}失败，邮箱账号{1}已存在", user.getUserName(), user.getEmail())));

        // 新增用户信息
        boolean retSave = this.save(user);
        // 新增用户岗位关联
        insertUserPost(user);
        // 新增用户与角色管理
        insertUserRole(user.getUserId(), user.getRoleIds());
        return retSave;
    }

    /**
     * 修改保存用户信息
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    @Transactional
    public boolean updateUser(SysUserVo user) {
        //校验用户是否允许操作
        checkUserAllowed(null, user.getUserId());
        //校验用户是否有数据权限
        checkUserDataScope(user.getUserId());

        Assert.isFalse(SqlHelper.retBool(this.count(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getUserId, user.getUserId())
                        .eq(SysUser::getUserName, user.getUserName()).eq(SysUser::getDelFlag, ComConstant.FLAG_EXIST))),
                () -> new BizException(MessageFormat.format("修改用户{0}失败，登录账号已存在", user.getUserName())));

        Assert.isFalse(StrUtil.isNotBlank(user.getPhonenumber()) && SqlHelper.retBool(this.count(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getUserId, user.getUserId())
                        .eq(SysUser::getPhonenumber, user.getPhonenumber()).eq(SysUser::getDelFlag, ComConstant.FLAG_EXIST))),
                () -> new BizException(MessageFormat.format("修改用户{0}失败，手机号码{1}已存在", user.getUserName(), user.getPhonenumber())));

        Assert.isFalse(StrUtil.isNotBlank(user.getEmail()) && SqlHelper.retBool(this.count(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getUserId, user.getUserId())
                        .eq(SysUser::getEmail, user.getEmail()).eq(SysUser::getDelFlag, ComConstant.FLAG_EXIST))),
                () -> new BizException(MessageFormat.format("修改用户{0}失败，邮箱账号{1}已存在", user.getUserName(), user.getEmail())));

        Long userId = user.getUserId();
        // 删除用户与角色关联
        sysUserRoleService.removeById(userId);
        // 新增用户与角色管理
        insertUserRole(user.getUserId(), user.getRoleIds());
        // 删除用户与岗位关联
        sysUserPostService.removeById(userId);
        // 新增用户与岗位管理
        insertUserPost(user);
        return this.updateById(user);
    }

    /**
     * 通过用户ID查询用户
     *
     * @param userId 用户ID
     * @return 用户对象信息
     */
    @Override
    public SysUserVo selectUserById(Long userId) {
        //校验用户是否有数据权限
        checkUserDataScope(userId);
        SysUserVo convert = Convert.convert(SysUserVo.class, this.getById(userId));
        //获取该用户的所有角色ID
        List<Long> roleIds = sysUserRoleService.listByIds(Collections.singletonList(userId))
                .stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(roleIds)) {
            convert.setRoleIds(roleIds.toArray(new Long[0]));
            convert.setRoles(Convert.toList(SysRoleVo.class, sysRoleService.listByIds(roleIds)));
        }
        //获取该用户的所有岗位
        List<Long> postIds = sysUserPostService.listByIds(Collections.singletonList(userId))
                .stream().map(SysUserPost::getPostId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(postIds)) {
            convert.setPostIds(postIds.toArray(new Long[0]));
            convert.setPosts(Convert.toList(SysPostVo.class, sysPostService.listByIds(postIds)));
        }
        //获取该用户的部门信息
        if (Objects.nonNull(convert.getDeptId())) {
            convert.setDept(sysDeptService.selectDeptById(convert.getDeptId()));
        }
        return convert;
    }

    /**
     * 批量删除用户信息
     *
     * @param userIds 需要删除的用户ID
     * @return 结果
     */
    @Override
    @Transactional
    public boolean deleteUserByIds(Long[] userIds) {
        for (Long userId : userIds) {
            //校验用户是否允许操作
            checkUserAllowed(null, userId);
            //校验用户是否有数据权限
            checkUserDataScope(userId);
        }
        // 删除用户与角色关联
        sysUserRoleService.removeBatchByIds(Arrays.asList(userIds));
        // 删除用户与岗位关联
        sysUserPostService.removeBatchByIds(Arrays.asList(userIds));
        return this.removeBatchByIds(Arrays.asList(userIds));
    }

    /**
     * 重置用户密码
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public boolean resetPwd(SysUserVo user) {
        Long userId = user.getUserId();
        //校验用户是否允许操作
        checkUserAllowed(null, userId);
        //校验用户是否有数据权限
        checkUserDataScope(userId);
        return this.updateById(user);
    }

    /**
     * 修改用户状态
     *
     * @param user 用户信息
     * @return 结果
     */
    @Override
    public boolean updateUserStatus(SysUser user) {
        Long userId = user.getUserId();
        //校验用户是否允许操作
        checkUserAllowed(null, userId);
        //校验用户是否有数据权限
        checkUserDataScope(userId);
        return this.updateById(user);
    }

    /**
     * 用户授权角色
     *
     * @param userId  用户ID
     * @param roleIds 角色组
     * @return
     */
    @Override
    @Transactional
    public boolean insertUserAuth(Long userId, Long[] roleIds) {
        //校验用户是否有数据权限
        checkUserDataScope(userId);
        //删除用户角色关联表
        sysUserRoleService.removeById(userId);
        //插入新的用户角色关联表
        insertUserRole(userId, roleIds);
        return true;
    }


    @Override
    public SysUserVo selectUserByUserName(String username) {
        SysUser one = this.getOne(Wrappers.lambdaQuery(SysUser.class).eq(SysUser::getUserName, username)
                .eq(SysUser::getStatus, ComConstant.STATUS_NORMAL).last("limit 1"));
        return Objects.isNull(one) ? null : this.selectUserById(one.getUserId());
    }

    @Override
    public boolean updateUserProfile(SysUser sysUser) {
        return this.updateById(sysUser);
    }
//
// /**
//  * 根据条件分页查询已分配用户角色列表
//  *
//  * @param user 用户信息
//  * @return 用户信息集合信息
//  */
// @Override
// @DataScope(deptAlias = "d", userAlias = "u")
// public List<SysUser> selectAllocatedList(SysUser user) {
//  return userMapper.selectAllocatedList(user);
// }
//
// /**
//  * 根据条件分页查询未分配用户角色列表
//  *
//  * @param user 用户信息
//  * @return 用户信息集合信息
//  */
// @Override
// @DataScope(deptAlias = "d", userAlias = "u")
// public List<SysUser> selectUnallocatedList(SysUser user) {
//  return userMapper.selectUnallocatedList(user);
// }
//
// /**
//  * 通过用户名查询用户
//  *
//  * @param userName 用户名
//  * @return 用户对象信息
//  */
// @Override
// public SysUser selectUserByUserName(String userName) {
//  return userMapper.selectUserByUserName(userName);
// }
//
//
// /**
//  * 查询用户所属角色组
//  *
//  * @param userName 用户名
//  * @return 结果
//  */
// @Override
// public String selectUserRoleGroup(String userName) {
//  List<SysRole> list = roleMapper.selectRolesByUserName(userName);
//  if (CollectionUtils.isEmpty(list)) {
//   return StringUtils.EMPTY;
//  }
//  return list.stream().map(SysRole::getRoleName).collect(Collectors.joining(","));
// }
//
// /**
//  * 查询用户所属岗位组
//  *
//  * @param userName 用户名
//  * @return 结果
//  */
// @Override
// public String selectUserPostGroup(String userName) {
//  List<SysPost> list = postMapper.selectPostsByUserName(userName);
//  if (CollectionUtils.isEmpty(list)) {
//   return StringUtils.EMPTY;
//  }
//  return list.stream().map(SysPost::getPostName).collect(Collectors.joining(","));
// }
//
// /**
//  * 校验用户名称是否唯一
//  *
//  * @param user 用户信息
//  * @return 结果
//  */
// @Override
// public boolean checkUserNameUnique(SysUser user) {
//  Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
//  SysUser info = userMapper.checkUserNameUnique(user.getUserName());
//  if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) {
//   return UserConstants.NOT_UNIQUE;
//  }
//  return UserConstants.UNIQUE;
// }
//
// /**
//  * 校验手机号码是否唯一
//  *
//  * @param user 用户信息
//  * @return
//  */
// @Override
// public boolean checkPhoneUnique(SysUser user) {
//  Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
//  SysUser info = userMapper.checkPhoneUnique(user.getPhonenumber());
//  if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) {
//   return UserConstants.NOT_UNIQUE;
//  }
//  return UserConstants.UNIQUE;
// }
//
// /**
//  * 校验email是否唯一
//  *
//  * @param user 用户信息
//  * @return
//  */
// @Override
// public boolean checkEmailUnique(SysUser user) {
//  Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
//  SysUser info = userMapper.checkEmailUnique(user.getEmail());
//  if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue()) {
//   return UserConstants.NOT_UNIQUE;
//  }
//  return UserConstants.UNIQUE;
// }
//
//
// /**
//  * 注册用户信息
//  *
//  * @param user 用户信息
//  * @return 结果
//  */
// @Override
// public boolean registerUser(SysUser user) {
//  return userMapper.insertUser(user) > 0;
// }
//
// /**
//  * 修改用户基本信息
//  *
//  * @param user 用户信息
//  * @return 结果
//  */
// @Override
// public int updateUserProfile(SysUser user) {
//  return userMapper.updateUser(user);
// }
//
// /**
//  * 修改用户头像
//  *
//  * @param userName 用户名
//  * @param avatar   头像地址
//  * @return 结果
//  */
// @Override
// public boolean updateUserAvatar(String userName, String avatar) {
//  return userMapper.updateUserAvatar(userName, avatar) > 0;
// }
//
//
// /**
//  * 重置用户密码
//  *
//  * @param userName 用户名
//  * @param password 密码
//  * @return 结果
//  */
// @Override
// public int resetUserPwd(String userName, String password) {
//  return userMapper.resetUserPwd(userName, password);
// }
//
//
// /**
//  * 通过用户ID删除用户
//  *
//  * @param userId 用户ID
//  * @return 结果
//  */
// @Override
// @Transactional
// public int deleteUserById(Long userId) {
//  // 删除用户与角色关联
//  userRoleMapper.deleteUserRoleByUserId(userId);
//  // 删除用户与岗位表
//  userPostMapper.deleteUserPostByUserId(userId);
//  return userMapper.deleteUserById(userId);
// }
//
//
// /**
//  * 导入用户数据
//  *
//  * @param userList  用户数据列表
//  * @param isUpdateSupport 是否更新支持，如果已存在，则进行更新数据
//  * @param operName  操作用户
//  * @return 结果
//  */
// @Override
// public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName) {
//  if (StringUtils.isNull(userList) || userList.size() == 0) {
//   throw new ServiceException("导入用户数据不能为空！");
//  }
//  int successNum = 0;
//  int failureNum = 0;
//  StringBuilder successMsg = new StringBuilder();
//  StringBuilder failureMsg = new StringBuilder();
//  String password = configService.selectConfigByKey("sys.user.initPassword");
//  for (SysUser user : userList) {
//   try {
//    // 验证是否存在这个用户
//    SysUser u = userMapper.selectUserByUserName(user.getUserName());
//    if (StringUtils.isNull(u)) {
//     BeanValidators.validateWithException(validator, user);
//     user.setPassword(SecurityUtils.encryptPassword(password));
//     user.setCreateBy(operName);
//     this.insertUser(user);
//     successNum++;
//     successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 导入成功");
//    } else if (isUpdateSupport) {
//     BeanValidators.validateWithException(validator, user);
//     checkUserAllowed(user);
//     checkUserDataScope(user.getUserId());
//     user.setUpdateBy(operName);
//     this.updateUser(user);
//     successNum++;
//     successMsg.append("<br/>" + successNum + "、账号 " + user.getUserName() + " 更新成功");
//    } else {
//     failureNum++;
//     failureMsg.append("<br/>" + failureNum + "、账号 " + user.getUserName() + " 已存在");
//    }
//   } catch (Exception e) {
//    failureNum++;
//    String msg = "<br/>" + failureNum + "、账号 " + user.getUserName() + " 导入失败：";
//    failureMsg.append(msg + e.getMessage());
//    log.error(msg, e);
//   }
//  }
//  if (failureNum > 0) {
//   failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
//   throw new ServiceException(failureMsg.toString());
//  } else {
//   successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
//  }
//  return successMsg.toString();
// }

    /**
     * 新增用户岗位信息
     *
     * @param user 用户对象
     */
    private void insertUserPost(SysUserVo user) {
        Long[] posts = user.getPostIds();
        if (Objects.nonNull(posts)) {
            sysUserPostService.saveBatch(Arrays.stream(posts).map(postId -> new SysUserPost(user.getUserId(), postId)).collect(Collectors.toList()));
        }
    }

    /**
     * 新增用户角色信息
     *
     * @param userId  用户ID
     * @param roleIds 角色组
     */
    private void insertUserRole(Long userId, Long[] roleIds) {
        if (Objects.nonNull(roleIds)) {
            sysUserRoleService.saveBatch(Arrays.stream(roleIds).map(roleId -> new SysUserRole(userId, roleId)).collect(Collectors.toList()));
        }
    }

    /**
     * 校验用户是否允许操作
     *
     * @param user 用户信息
     */
    private void checkUserAllowed(SysUser user, Long userId) {
        Assert.isFalse((Objects.nonNull(user) && user.isAdmin()) || (Objects.nonNull(userId) && SysUserVo.isAdmin(userId)), () -> new BizException("不允许操作超级管理员用户"));
    }

    /**
     * 校验用户是否有数据权限
     *
     * @param userId 用户id
     */
    private void checkUserDataScope(Long userId) {
        Assert.isFalse(!SecurityUtils.isCurrentUserAdmin() &&
                CollUtil.isEmpty(((SysUserService) AopContext.currentProxy()).selectUserList(SysUserDto.builder().userId(userId).build())), () -> new BizException("没有权限访问用户数据"));

    }

}
